package NWPackage;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import Readers.InputsReader;
//import Writers.MsgLog;

public class Algorithms {
	
	public static List<PairPreferdCandidateCell> askedQueries;
	public static List<String> necessaryWinners;
	public static List<String> possibleWinners;
	public static int numberOfRightGuesses;
	
	public static void NecessaryWinnerAlgorithm(Protocol protocol,ProbabilitiesMatrix probMatrix, RealVoteMatrix realVoteMatrix, QueryFinderAlg QueryFinder,boolean flag) throws Exception
	{
		numberOfRightGuesses = 0;
		askedQueries = new ArrayList<PairPreferdCandidateCell>();
		
		//initial the Pairs Preferred Candidate Matrix for all voters
		PairPreferdCandidateMatrix pairsPreferredMatrix  = new PairPreferdCandidateMatrix();
		pairsPreferredMatrix.initial();
		
		//init the Necessary and Optional Winners Lists:
		necessaryWinners = new ArrayList<String>();
		possibleWinners =Arrays.asList(InputsReader.getCandidates());	
		List<String> allCands = Arrays.asList(InputsReader.getCandidates());
		
	//	printArray(necessaryWinners, "necessary");
	//	printArray(possibleWinners, "possible");
		
		//initial calc min_max from the matrix using protocol
		protocol.initial_calcMinMax(possibleWinners);
		
		int while_counter = 0;
		//until winner is not found and there are still optional Candidates:
		while (necessaryWinners.isEmpty() && !possibleWinners.isEmpty())
		{			 							
			PairPreferdCandidateCell query = (PairPreferdCandidateCell)QueryFinder.FindNextQuery(probMatrix,pairsPreferredMatrix,possibleWinners,protocol);
			if (query!=null){				
				// Query the Agent about his preferred Candidate
			
			 
				//--------Debug Only---------------------------------------------------------//
							
				//get the real vote
				String realVote = realVoteMatrix.getRealVote(query);
				//set the real vote
				query.setPrefered_C(realVote);
				//get the cands by the preferred order
				String[] cands = query.getCandidatesByPrefferedOrder();
											
			//	System.out.print(while_counter + ": preferred_cand: " + query.getAlgPrefferedCandidate()+ " winner_cands: " + protocol.findMaxCandidate(possibleWinners));
			//	System.out.print("  NewQuery: " + query.getAgentName() + ": " + cands[0].toString() + " < " + cands[1].toString());	
												
				numberOfRightGuesses += (realVote == query.getAlgPrefferedCandidate()) ? 1 : 0 ;
				//--------------------------------------------------------------------------//
				
				//add query to the Asked_Queries List for further statistics:
				askedQueries.add(query);
				
				//calc min_max from the matrix using protocol
				protocol.calcMinMax(query,allCands);
				
				
				//check for necessary / possible winners using the protocol
				necessaryWinners = protocol.UpdateNecessary(possibleWinners);
				possibleWinners = protocol.UpdatePossible(possibleWinners);
				
			//	printArray(necessaryWinners, "necessary");
			//	printArray(possibleWinners, "possible");
												
				
				int x =  protocol.get_minSum_for_cand(cands[1]);
				int y = protocol.get_maxSum_for_cand(cands[0]);
			//	System.out.println("  cand:" + cands[0] + " max= " +  y  + "  cand:" + cands[1] + " min " + x );  											 
		//		System.out.println();
				//get automate queries we have found via transitive Closure
				List<PairPreferdCandidateCell> allNewQueries = protocol.getAllNewQueries();
				
				//Update The Probability Matrix
				//------DEBUG WITHOUT THE MATRIX NORMALIZATION-----------//
				if (flag)   //we do not update (or use) the probMatrix in algos that don't use probs
				   probMatrix = UpdateProbMatrix(probMatrix,allNewQueries);
				
				//Update the Agent's preferred Answer in the Pairs Preferred Matrix
				//So next iteration we wont check this query again
			//	pairsPreferredMatrix = UpdateVoteMatrix(pairsPreferredMatrix,allNewQueries,probMatrix);
				UpdateVoteMatrix(pairsPreferredMatrix,allNewQueries);
				if (flag)
					updateOneVotes(pairsPreferredMatrix,allNewQueries,probMatrix);				
			}
			else{
				System.out.println ("query is null");
			}
			while_counter++;
			
	
		}
		//
	}	

	private static ProbabilitiesMatrix UpdateProbMatrix(ProbabilitiesMatrix probMatrix, List<PairPreferdCandidateCell> allNewQueries) {
		for (PairPreferdCandidateCell query : allNewQueries) {
			probMatrix = probMatrix.normalize(query);
			probMatrix.UpdateSumOfProbabilities();
		}
		return probMatrix;
		
	}
	
	private static void printArray (List<String> arr, String str){
		System.out.println("print array " + str);
		System.out.println(arr.toString());
		
	}

	//get answers for all queries we found from Transitive Closure
	//and from the Prob Matrix - when agent have prob=1 for one choice
	private static void UpdateVoteMatrix(PairPreferdCandidateMatrix pairsPreferredMatrix,
			List<PairPreferdCandidateCell> allNewQueries) {
		
		//check new queries (transitive closure)
		if (allNewQueries.size()>1)
		{
			for (PairPreferdCandidateCell query : allNewQueries) {
				pairsPreferredMatrix.setVote(query);
			}
		}
		
	/*	//check if exist agent with only one probability Cell (probability = 1)
		List<ProbabilityCell> lastCells = probMatrix.getOneLeftProbCells();
		
		for (ProbabilityCell probabilityCell : lastCells) {
			List<PairPreferdCandidateCell> new_queries = probabilityCell.extractQueries();
			if (new_queries.size()>1)
			{
				for (PairPreferdCandidateCell query : allNewQueries) {
					pairsPreferredMatrix.setVote(query);
				}
			}
		}*/
		//return pairsPreferredMatrix;		
	}
	
	private static void updateOneVotes (PairPreferdCandidateMatrix pairsPreferredMatrix,
			List<PairPreferdCandidateCell> allNewQueries, ProbabilitiesMatrix probMatrix){
		//check if exist agent with only one probability Cell (probability = 1)
				List<ProbabilityCell> lastCells = probMatrix.getOneLeftProbCells();
				
				for (ProbabilityCell probabilityCell : lastCells) {
					List<PairPreferdCandidateCell> new_queries = probabilityCell.extractQueries();
					if (new_queries.size()>1)
					{
						for (PairPreferdCandidateCell query : allNewQueries) {
							pairsPreferredMatrix.setVote(query);
						}
					}
				}						
	}
	
	 

}
